"""
云端API服务模块
用于与云端服务器进行通信，获取会话ID等操作
使用HTTP请求与服务器交互，处理会话创建、状态同步等功能
原理：通过HTTP客户端向云端服务器发送请求，获取新的会话ID并处理响应

新增功能：
- 原始数据传送到云端存储服务
- 数据格式转换和封装
- 批量数据传送支持
"""

import requests
import json
import os
from typing import Optional, Dict, Any, List
from datetime import datetime

from ..models.cloud_storage_models import (
    CloudStorageEEGData, 
    CloudStorageResponse, 
    TabletRawData,
    WaveData,
    WaveFrames,
    FrequencyBandData,
    RawValuePoint,
    RealtimeDataRequest,
    RealtimeDataResponse,
    RealtimeDataPoint
)
from ..models.brain_wave_data import FrequencyData


class CloudAPIService:
    """云端API服务类，负责与服务器通信"""
    
    def __init__(self, base_url: str = "http://localhost:8000/api"):
        """
        初始化云端API服务
        
        Args:
            base_url: 服务器API基础URL
        """
        self.base_url = base_url
        self.timeout = 30  # 请求超时时间（秒）
        
        # 云端存储服务配置（简化版本，不使用API密钥）
        self.cloud_storage_base_url = os.getenv("CLOUD_STORAGE_BASE_URL", "https://storage.example.com")
        self.raw_data_upload_endpoint = os.getenv("RAW_DATA_UPLOAD_ENDPOINT", "/eeg/raw")
        self.realtime_data_endpoint = os.getenv("REALTIME_DATA_ENDPOINT", "/analysis/data")
        self.raw_data_upload_timeout = int(os.getenv("RAW_DATA_UPLOAD_TIMEOUT", "60"))
        self.realtime_data_timeout = int(os.getenv("REALTIME_DATA_TIMEOUT", "30"))
    
    def create_session(self) -> Optional[int]:
        """
        向云端服务器请求创建新会话
            
        Returns:
            会话ID，如果请求失败返回None
        """
        try:
            url = f"{self.base_url}/sessions"
            payload = {
                "created_at": datetime.now().isoformat()
            }
            
            response = requests.post(
                url,
                json=payload,
                timeout=self.timeout,
                headers={"Content-Type": "application/json"}
            )
            
            if response.status_code == 201:
                data = response.json()
                return data.get("id")
            else:
                print(f"创建会话失败，状态码: {response.status_code}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"请求云端服务器失败: {e}")
            return None
        except json.JSONDecodeError as e:
            print(f"解析服务器响应失败: {e}")
            return None

    def convert_tablet_data_to_cloud_storage(self, tablet_data_list: List[TabletRawData]) -> CloudStorageEEGData:
        """
        将平板端数据转换为云端存储格式
        
        Args:
            tablet_data_list: 平板端原始数据列表（10-15秒的数据）
            
        Returns:
            CloudStorageEEGData: 云端存储格式的数据，包含时间戳和序列号
        """
        if not tablet_data_list:
            raise ValueError("平板端数据列表不能为空")
        
        # 使用第一个数据包的基础信息
        first_data = tablet_data_list[0]
        
        # 收集所有原始数据点，按时间戳排序
        raw_wave_frames = []
        filtered_wave_frames = []
        
        # 收集所有频段数据
        delta_frames = []
        theta_frames = []
        low_alpha_frames = []
        high_alpha_frames = []
        low_beta_frames = []
        high_beta_frames = []
        low_gamma_frames = []
        mid_gamma_frames = []
        
        # 收集所有原始数据点并按时间戳排序
        all_raw_points = []
        for tablet_data in tablet_data_list:
            for raw_point in tablet_data.raw_data:  # 修改从raw_value到raw_data
                all_raw_points.append((raw_point.timestamp, raw_point.value))
        
        # 按时间戳排序确保数据有序
        all_raw_points.sort(key=lambda x: x[0])
        
        # 提取排序后的数值
        for timestamp, value in all_raw_points:
            raw_wave_frames.append(value)
            # 假设过滤后的数据与原始数据相同（实际项目中可能需要真实的过滤算法）
            filtered_wave_frames.append(value)
        
        # 处理频段数据 - 使用第一个原始数据点的时间戳作为排序依据
        # 由于TabletRawData没有timestamp字段，我们使用raw_data中第一个点的时间戳
        tablet_data_sorted = sorted(tablet_data_list, key=lambda x: x.raw_data[0].timestamp if x.raw_data else 0)
        for tablet_data in tablet_data_sorted:
            delta_frames.append(tablet_data.delta)
            theta_frames.append(tablet_data.theta)
            low_alpha_frames.append(tablet_data.low_alpha)
            high_alpha_frames.append(tablet_data.high_alpha)
            low_beta_frames.append(tablet_data.low_beta)
            high_beta_frames.append(tablet_data.high_beta)
            low_gamma_frames.append(tablet_data.low_gamma)
            mid_gamma_frames.append(tablet_data.mid_gamma)
        
        # 计算数据包时间信息
        start_timestamp = min(point[0] for point in all_raw_points) / 1000.0  # 转换为秒
        end_timestamp = max(point[0] for point in all_raw_points) / 1000.0
        duration_seconds = end_timestamp - start_timestamp
        
        # 生成序列号（基于时间戳）
        sequence_number = int(start_timestamp)
        
        # 构建云端存储格式数据
        cloud_storage_data = CloudStorageEEGData(
            id=str(first_data.session_id),  # 转换为字符串
            room_id=first_data.room_id,
            data_timestamp=start_timestamp,  # 数据采集开始时间戳
            duration_seconds=duration_seconds,  # 数据包时长
            sequence_number=sequence_number,  # 数据包序号
            eeg_wave_data=WaveData(
                frame_rate=512,  # 假设采样率为512Hz
                wave=WaveFrames(frames=raw_wave_frames),
                filtered=WaveFrames(frames=filtered_wave_frames)
            ),
            delta_data=FrequencyBandData(
                frame_rate=1,  # 频段数据每秒1个数据点
                wave=WaveFrames(frames=delta_frames),
                filtered=WaveFrames(frames=delta_frames)  # 假设过滤后数据相同
            ),
            theta_data=FrequencyBandData(
                frame_rate=1,
                wave=WaveFrames(frames=theta_frames),
                filtered=WaveFrames(frames=theta_frames)
            ),
            low_alpha_data=FrequencyBandData(
                frame_rate=1,
                wave=WaveFrames(frames=low_alpha_frames),
                filtered=WaveFrames(frames=low_alpha_frames)
            ),
            high_alpha_data=FrequencyBandData(
                frame_rate=1,
                wave=WaveFrames(frames=high_alpha_frames),
                filtered=WaveFrames(frames=high_alpha_frames)
            ),
            low_beta_data=FrequencyBandData(
                frame_rate=1,
                wave=WaveFrames(frames=low_beta_frames),
                filtered=WaveFrames(frames=low_beta_frames)
            ),
            high_beta_data=FrequencyBandData(
                frame_rate=1,
                wave=WaveFrames(frames=high_beta_frames),
                filtered=WaveFrames(frames=high_beta_frames)
            ),
            low_gamma_data=FrequencyBandData(
                frame_rate=1,
                wave=WaveFrames(frames=low_gamma_frames),
                filtered=WaveFrames(frames=low_gamma_frames)
            ),
            mid_gamma_data=FrequencyBandData(
                frame_rate=1,
                wave=WaveFrames(frames=mid_gamma_frames),
                filtered=WaveFrames(frames=mid_gamma_frames)
            )
        )
        
        return cloud_storage_data

    def upload_raw_data_to_cloud_storage(self, tablet_data_list: List[TabletRawData]) -> Optional[CloudStorageResponse]:
        """
        将原始数据上传到云端存储服务
        
        Args:
            tablet_data_list: 平板端原始数据列表（10-15秒的数据）
            
        Returns:
            CloudStorageResponse: 云端存储服务响应，失败返回None
        """
        try:
            # 转换数据格式
            cloud_storage_data = self.convert_tablet_data_to_cloud_storage(tablet_data_list)
            
            # 构建请求URL - 不添加session_id到URL路径
            base_url = self.cloud_storage_base_url.rstrip('/')
            endpoint = self.raw_data_upload_endpoint.lstrip('/')
            url = f"{base_url}/{endpoint}"
            
            print(f"发送原始数据到云端存储: {url}")
            print(f"数据包大小: {len(json.dumps(cloud_storage_data.model_dump()))} bytes")
            
            # 准备请求头（简化版本，不使用认证）
            headers = {
                "Content-Type": "application/json"
            }
            
            # 发送POST请求
            response = requests.post(
                url,
                json=cloud_storage_data.model_dump(),
                headers=headers,
                timeout=self.raw_data_upload_timeout
            )
            
            if response.status_code == 200:
                response_data = response.json()
                return CloudStorageResponse(
                    success=response_data.get("success", True),
                    message=response_data.get("message", "数据上传成功"),
                    data=response_data.get("data")
                )
            else:
                print(f"上传原始数据到云端存储失败，状态码: {response.status_code}")
                print(f"响应内容: {response.text}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"请求云端存储服务失败: {e}")
            return None
        except json.JSONDecodeError as e:
            print(f"解析云端存储服务响应失败: {e}")
            return None
        except Exception as e:
            print(f"上传原始数据时发生错误: {e}")
            return None
    
    def update_session_status(self, id: int, status: str) -> bool:
        """
        更新会话状态到云端服务器
        
        Args:
            id: 会话ID
            status: 新状态
            
        Returns:
            更新是否成功
        """
        try:
            url = f"{self.base_url}/sessions/{id}/status"
            payload = {
                "status": status,
                "updated_at": datetime.now().isoformat()
            }
            
            response = requests.put(
                url,
                json=payload,
                timeout=self.timeout,
                headers={"Content-Type": "application/json"}
            )
            
            return response.status_code == 200
            
        except requests.exceptions.RequestException as e:
            print(f"更新会话状态失败: {e}")
            return None


    def convert_brain_wave_data_to_realtime_request(self, brain_wave_data_list: List, room_id: str, session_id: str, user_state: str = "unknown", confidence: float = 0.0) -> RealtimeDataRequest:
        """
        将内部脑波数据模型转换为实时数据请求格式
        
        Args:
            brain_wave_data_list: 脑波数据列表（BrainWaveData对象列表）
            room_id: 房间ID
            session_id: 会话ID
            user_state: 用户状态（如awake, light_sleep等）
            confidence: 状态置信度
            
        Returns:
            RealtimeDataRequest: 实时数据请求对象
        """
        data_points = []
        
        for brain_wave_data in brain_wave_data_list:
            # 检查是否有频域数据
            if not brain_wave_data.frequency_data:
                # 如果没有频域数据，跳过或使用默认值
                continue
            
            freq_data = brain_wave_data.frequency_data
            
            # 计算各频段的总功率
            total_power = (
                freq_data.delta + freq_data.theta + 
                freq_data.low_alpha + freq_data.high_alpha +
                freq_data.low_beta + freq_data.high_beta +
                freq_data.low_gamma + freq_data.mid_gamma
            )
            
            # 避免除零错误
            if total_power == 0:
                total_power = 1.0
            
            # 合并Alpha、Beta、Gamma频段以匹配云端接口格式
            alpha_combined = (freq_data.low_alpha + freq_data.high_alpha) / total_power
            beta_combined = (freq_data.low_beta + freq_data.high_beta) / total_power
            gamma_combined = (freq_data.low_gamma + freq_data.mid_gamma) / total_power
            
            # 创建符合云端接口格式的数据点
            realtime_point = RealtimeDataPoint(
                timestamp=freq_data.timestamp.timestamp(),
                state=user_state,
                confidence=confidence,
                delta=round(freq_data.delta / total_power, 4),
                theta=round(freq_data.theta / total_power, 4),
                alpha=round(alpha_combined, 4),
                beta=round(beta_combined, 4),
                gamma=round(gamma_combined, 4)
            )
            
            data_points.append(realtime_point)
        
        return RealtimeDataRequest(
            session_id=session_id,
            room_id=room_id,
            user_id="default_user",
            data=data_points
        )


    def send_realtime_data_to_cloud_storage(self, session_id: str, realtime_request: RealtimeDataRequest) -> Optional[RealtimeDataResponse]:
        """
        发送实时数据到云端存储服务
        
        Args:
            session_id: 会话ID
            realtime_request: 实时数据请求对象
            
        Returns:
            RealtimeDataResponse: 云端存储服务响应，失败时返回None
        """
        try:
            # 构建请求URL - 不添加session_id到URL路径
            base_url = self.cloud_storage_base_url.rstrip('/')
            endpoint = self.realtime_data_endpoint.lstrip('/')
            url = f"{base_url}/{endpoint}"
            
            # 转换为云端API期望的格式
            cloud_data_points = []
            for point in realtime_request.data:
                # 直接使用RealtimeDataPoint的属性，不需要合并
                cloud_point = {
                    "timestamp": point.timestamp,
                    "state": point.state,
                    "confidence": point.confidence,
                    "delta": point.delta,
                    "theta": point.theta,
                    "alpha": point.alpha,
                    "beta": point.beta,
                    "gamma": point.gamma
                }
                cloud_data_points.append(cloud_point)
            
            # 准备请求数据 - 使用云端API格式
            request_data = {
                "session_id": session_id,
                "room_id": realtime_request.room_id,
                "user_id": realtime_request.user_id,
                "data": cloud_data_points
            }
            
            print(f"发送实时数据到云端存储: {url}")
            print(f"数据点数量: {len(cloud_data_points)}")
            
            # 发送POST请求
            response = requests.post(
                url,
                json=request_data,
                timeout=self.realtime_data_timeout,
                headers={"Content-Type": "application/json"}
            )
            
            if response.status_code == 200:
                response_data = response.json()
                return RealtimeDataResponse(
                    status=response_data.get("status", "success"),
                    message=response_data.get("message", "实时数据发送成功"),
                    data=response_data.get("data")
                )
            else:
                print(f"实时数据发送失败，状态码: {response.status_code}")
                print(f"响应内容: {response.text}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"发送实时数据到云端存储失败: {e}")
            return None
        except Exception as e:
            print(f"处理实时数据发送时发生错误: {e}")
            return None

    def get_session_info(self, id: int) -> Optional[Dict[str, Any]]:
        """
        从云端服务器获取会话信息
        
        Args:
            id: 会话ID
            
        Returns:
            会话信息字典，如果获取失败返回None
        """
        try:
            url = f"{self.base_url}/sessions/{id}"
            
            response = requests.get(
                url,
                timeout=self.timeout,
                headers={"Content-Type": "application/json"}
            )
            
            if response.status_code == 200:
                return response.json()
            else:
                print(f"获取会话信息失败，状态码: {response.status_code}")
                return None
                
        except requests.exceptions.RequestException as e:
            print(f"请求云端服务器失败: {e}")
            return None
        except json.JSONDecodeError as e:
            print(f"解析服务器响应失败: {e}")
            return None


# 全局云端API服务实例
_cloud_api_service = None


def get_cloud_api_service() -> CloudAPIService:
    """获取云端API服务单例实例"""
    global _cloud_api_service
    if _cloud_api_service is None:
        _cloud_api_service = CloudAPIService()
    return _cloud_api_service